import hashlib
import os
from djongo import models
from django.utils.translation import gettext_lazy as _
import json
# from django.core.serializers.json import DjangoJSONEncoder
# from cews.models import WorkOrderList
from django.contrib.auth.models import User
import datetime
from django.utils import timezone

class EformSchema(models.Model):
    endorsor_require_choices = [
        (False,'No'),
        (True,'Yes'),
    ]
    # id = models.ObjectIdField()
    title = models.CharField(_("Form Title"), max_length=500)
    formNo = models.CharField(_("Form No."), max_length=255)
    ref = models.CharField(_("Ref"), max_length=500)
    issue = models.CharField(_("Issue"), max_length=500,default="")
    formSchema = models.JSONField('Form Schema')


    ## if the form endorsor_require == False, no verify and endorse needed
    endorsor_require = models.BooleanField(_("Endorsor require"),choices=endorsor_require_choices)
    
    
    form_issue_date = models.DateTimeField(_(""), blank=True,null=True)
    created = models.DateTimeField('created',default=timezone.now)
    updated = models.DateTimeField('updated',default=timezone.now)
    enable = models.BooleanField(_("Enable"),default=True)

    def getInput(self,components,out=[]):
    # components = self.formSchema['components']
        for obj in components:
            if "input" in obj and obj['input']:
                out.append(obj['key'])
            elif 'components' in  obj:
                # print('found')
                self.getInput(obj['components'],out)
            elif 'rows' in obj:
                rows = obj['rows']
                for r in rows:
                    self.getInput(r,out)

    def getRequiredInput(self,components,out=[]):
        # components = self.formSchema['components']
        for obj in components:
            if "input" in obj and obj['input'] :
                    try:
                        required = obj['validate']['required']
                    except:
                        required = False
                    if required:
                        out.append(obj['key'])
            if 'components' in  obj:
                # print('found')
                self.getRequiredInput(obj['components'],out)
            elif 'rows' in obj:
                rows = obj['rows']
                for r in rows:
                    self.getRequiredInput(r,out)


    @property   
    def getFormJSON(self):
        return json.dumps(self.formSchema)

    
    def __str__(self):
        return f"{self.formNo}"

# class TestingEquipment(models.Model):
#     # # id = models.ObjectIdField()
#     name = models.CharField(_("Equipement Name"), max_length=500)
#     expiry = models.DateTimeField(_("Expiry Date"), auto_now=False, auto_now_add=False)

# class TestEquipmentRecord(models.Model):
#     class Meta:
#         abstract = True
#     testingEquipment = models.CharField(_("TestingEquipmentKey"), max_length=500)
#     expiry = models.DateTimeField(_("Expiry Date"), auto_now=False, auto_now_add=False)

class Eform(models.Model):
    
    class Meta:
        permissions = [
            ('can_endorsed','Can Endorsed'),
            ('can_verified','Can Verified'),
            ('can_reset_endorsed','Can Reset Endorsed'),
        ]

    
    eform_status_choice = [
        (0,'In Progress'),
        (1,'Done'),
        (2,'Verified'),
        (3,'Endorsed'),
    ]

    overall_test_result_choices = [
        ('Pass','Pass'),
        ('Fail','Fail'),
    ]
    # # id = models.ObjectIdField()
    
    eformSchema = models.ForeignKey('eform.EformSchema',verbose_name='Eform Schema',on_delete=models.PROTECT)
    # workOrderList = models.ForeignKey("cews.WorkOrderList", verbose_name=_("Work Order List"), on_delete=models.PROTECT,blank=True, null=True)
    
    workOrderList_pk = models.IntegerField(_("WorkOrderListPk"),blank=True,null=True)

    extFormSchema = models.JSONField(_("Ext Form Schema"))
    schemaRetrieveDate = models.DateField(_("Schema Retrieve Date"), auto_now=True)
    
    ## Embedded
    formData = models.JSONField(_("Form Data"),default={})
    testingEquipmentRecord = models.ArrayField(model_container=TestEquipmentRecord)

    # doneby = models.ForeignKey("auth.User", verbose_name=_("Done by"),related_name="doneby", on_delete=models.CASCADE)
    # verifiedby = models.ForeignKey("auth.User", verbose_name=_("Verified by"),related_name="verifiedby", on_delete=models.CASCADE, null=True, blank=True)
    # endorsedby = models.ForeignKey("auth.User", verbose_name=_("Endorsed by"),related_name="endorsedby", on_delete=models.CASCADE, null=True, blank=True)
    doneby_id = models.IntegerField(_("doneby_id"),blank=True,null=True)
    verifiedby_id =models.IntegerField(_("verifiedby_id"),blank=True,null=True)
    endorsedby_id = models.IntegerField(_("endorsedby_id"),blank=True,null=True)
    

    # doneby = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_("Done by"),related_name="doneby", on_delete=models.CASCADE)
    # verifiedby = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_("Verified by"),related_name="verifiedby", on_delete=models.CASCADE, null=True, blank=True)
    # endorsedby = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_("Endorsed by"),related_name="endorsedby", on_delete=models.CASCADE, null=True, blank=True)
    

    doneDate = models.DateTimeField(_("Done Date"), auto_now=False, auto_now_add=False, null=True, blank=True)
    verifiedDate = models.DateTimeField(_("Verified Date"), auto_now=False, auto_now_add=False, null=True, blank=True)
    endorsedDate = models.DateTimeField(_("Endorsed Date"), auto_now=False, auto_now_add=False, null=True, blank=True)

    status = models.IntegerField(_("Status"),choices=eform_status_choice,default=0)
    # progress = models.FloatField(_("Progress Percentage"),default=0)

    overall_test_result = models.CharField(_('Overall Test Result'),max_length=255,choices=overall_test_result_choices,default="",blank=True)

    created = models.DateTimeField(_('Created'),auto_now=True)
    deleted = models.BooleanField(_("Deleted"),default=False)
    

    
    def checkUserDuplication(self,new_user_id):
        ids = []
        if self.doneby_id:
            ids.append(self.doneby_id)
        if self.verifiedby_id:
            ids.append(self.verifiedby_id)
        if self.endorsedby_id:
            ids.append(self.endorsedby_id)
        new_user_id = int(new_user_id)        
        return new_user_id in ids


    @property
    def workOrderList(self):
        # TODO: REVAMP THIS
        return False
        # ret = WorkOrderList.objects.filter(pk=self.workOrderList_pk).first()
        # if ret:
        #     return ret
        # else:
        #     return False

    @property
    def getProgress(self):
        keys = []
        com = self.extFormSchema['components']
        self.eformSchema.getRequiredInput(com,keys)
        
        if not len(keys):
            return False

        filled = 0
        for key,value in self.formData.items():
            if value and value !='':
                if key in keys:
                    filled +=1
        return round((filled / len(keys))*100)


    @property
    def getFormJSON(self):
        return json.dumps(self.extFormSchema)


    
    @property        
    def doneby(self):
        if not self.doneby_id:
            return None
        else:
            return User.objects.filter(pk=self.doneby_id).first()
    @property    
    def verifiedby(self):
        if not self.verifiedby_id:
            return None
        else:
            return User.objects.filter(pk=self.verifiedby_id).first()
    @property    
    def endorsedby(self):
        if not self.endorsedby_id:
            return None
        else:
            return User.objects.filter(pk=self.endorsedby_id).first()


    @property
    def getFormDataJson(self):
        # obj = {}
        # if self.formData:
        #     for d in self.formData:
        #         obj[d['key']] = d['data']
        #     return json.dumps(obj)
        # else:
        #     return {}
        if self.formData:
            return json.dumps(self.formData)
        else:
            return {}

class ReviseLog(models.Model):
    request_user_pk = models.IntegerField(_("request_user_pk"))
    approve_user_pk = models.IntegerField(_("approve_user_pk"))
    eform_pk = models.IntegerField(_("eform_pk"))
    
    remark = models.CharField(_("Remark"), max_length=500,default="")
    created = models.DateTimeField(_("Create"), auto_now=True)

    @property
    def request_user(self):
        return User.objects.filter(id=self.request_user_pk).first()

    @property
    def approve_user(self):
        return User.objects.filter(id=self.approve_user_pk).first()

    def __str__(self):
        return f"{self.created.strftime('%Y-%m-%d %H:%M:%S')} - {self.request_user.username} requested revising, approved by {self.approve_user.username}"

class EformLogs(models.Model):
    # # id = models.ObjectIdField()
    type_choices = [
        ('revise',_("revise"))
    ]
    remark = models.CharField(_("remark"), max_length=500,default="")
    type = models.CharField(_("Type"), max_length=255)
    eform = models.ForeignKey("eform.Eform", verbose_name=_("Eform"), on_delete=models.CASCADE)

    @property
    def user(self):
        return User.objects.filter(pk=self.user_pk)
    
    @property
    def desc(self):
        ret = f"ACTION: {self.get_type_display()} | User ID: {self.user_pk} | Eform ID: {self.eform.id}"
        if self.remark and self.remark!="":
            ret += f' | Remark: {self.remark}'
        return ret


def eformFileUploadTo(instance,filename):
    return '/'.join(['eformFile', hashlib.sha256(str(datetime.datetime.now()).encode()).hexdigest(),filename])

class EformFile(models.Model):

    file = models.FileField(_("File"), upload_to=eformFileUploadTo, max_length=1000)
    eform = models.ForeignKey("eform.Eform", verbose_name=_("Eform"), on_delete=models.CASCADE)
    desc =  models.CharField(_("File Description"), max_length=1024,default="")
    created = models.DateTimeField(_("Created"), auto_now=True)
    user_id = models.IntegerField(_("User ID"))

    @property
    def ext(self):
        if self.file:
            _, ext = os.path.splitext(self.file.name)
            return ext
        else:
            return False

    @property
    def filename(self):
        return self.file.name.split('/').pop()

    @property
    def isImage(self):
        try:
            return self.ext in ('.png','.jpg','.bmp')
        except Exception as ex:
            return False

    @property
    def isVideo(self):
        try:
            return self.ext in ('.mp4')
        except Exception as ex:
            return False

    @property
    def user(self):
        return User.objects.filter(id=self.user_id).first()


class EformPairing(models.Model):
    # _id = models.ObjectIdField()
    level6 = models.CharField(_("Level6"), max_length=255)
    formNo = models.CharField(_("formNo"), max_length=100)

    def __str__(self):
        return f"{self.level6} : {self.formNo}"